package logic

import (
	"Bluebell/common/snowflake"
	"Bluebell/dao/mysql"
	"Bluebell/dao/redis"
	"Bluebell/models"
	"go.uber.org/zap"
)

func CreatePost(p *models.Post) (err error) {
	p.PostID, err = snowflake.GetID()
	if err != nil {
		return err
	}
	err = mysql.CreatePost(p)
	return err
}

func GetPostDetail(id int64) (apipost *models.ApiPostDetail, err error) {
	apipost = new(models.ApiPostDetail)
	post, err := mysql.GetPost(id)
	if err != nil {
		zap.L().Error("dao.GetPost failed:", zap.Error(err))
		return
	}
	user, err := mysql.GetUserByID(post.AuthorId)
	if err != nil {
		zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
		return
	}
	apipost.Post = post
	apipost.AuthorName = user.UserName

	community, err := mysql.GetCommunityDetail(uint64(post.CommunityID))
	if err != nil {
		zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
		return
	}
	apipost.CommunityName = community.CommunityName
	return apipost, err
}

func GetPostList(page, size int64) (data []*models.ApiPostDetail, err error) {
	posts, err := mysql.GetPostList(page, size)
	if err != nil {
		return nil, err
	}
	data = make([]*models.ApiPostDetail, 0, len(posts))
	for _, post := range posts {
		user, err := mysql.GetUserByID(post.AuthorId)
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		community, err := mysql.GetCommunityDetail(uint64(post.CommunityID))
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:    user.UserName,
			Post:          post,
			CommunityName: community.CommunityName,
		}
		data = append(data, postDetail)
	}
	return data, err
}

func GetPostList2(p *models.ParamsPostList) (data []*models.ApiPostDetail, err error) {
	//查询id列表
	ids, err := redis.GetPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(ids) == 0 {
		zap.L().Warn("redis.GetPostIDsInOrder failed:", zap.Error(err))
		return
	}
	posts, err := mysql.GetPostListByIDs(ids)
	data = make([]*models.ApiPostDetail, 0, len(posts))

	//查询每篇帖子的点赞数
	voteData, err := redis.GetPostVoteData(ids)
	if err != nil {
		return
	}
	for idx, post := range posts {
		user, err := mysql.GetUserByID(post.AuthorId)
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		community, err := mysql.GetCommunityDetail(uint64(post.CommunityID))
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:    user.UserName,
			Post:          post,
			CommunityName: community.CommunityName,
			VoteNum:       voteData[idx],
		}
		data = append(data, postDetail)
	}
	return data, err
}

func GetCommunityPostList2(p *models.ParamsPostList) (data []*models.ApiPostDetail, err error) {
	//查询id列表
	ids, err := redis.GetCommunityPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(ids) == 0 {
		zap.L().Warn("redis.GetPostIDsInOrder failed:", zap.Error(err))
		return
	}
	posts, err := mysql.GetPostListByIDs(ids)
	data = make([]*models.ApiPostDetail, 0, len(posts))

	//查询每篇帖子的点赞数
	voteData, err := redis.GetPostVoteData(ids)
	if err != nil {
		return
	}
	for idx, post := range posts {
		user, err := mysql.GetUserByID(post.AuthorId)
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		community, err := mysql.GetCommunityDetail(uint64(post.CommunityID))
		if err != nil {
			zap.L().Error("dao.GetUserByUsername failed:", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:    user.UserName,
			Post:          post,
			CommunityName: community.CommunityName,
			VoteNum:       voteData[idx],
		}
		data = append(data, postDetail)
	}
	return data, err
}

func GetPostListNew(p *models.ParamsPostList) (data []*models.ApiPostDetail, err error) {
	if p.CommunityID == 0 {
		data, err = GetPostList2(p)
	} else {
		data, err = GetCommunityPostList2(p)
	}
	if err != nil {
		zap.L().Error("GetPostListNew failed:", zap.Error(err))
		return nil, err
	}
	return
}
